package org.footballmanager.pandafootball.system.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.RowBounds;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.footballmanager.pandafootball.common.util.SpiderUtil;
import org.footballmanager.pandafootball.system.dao.PageDao;
import org.footballmanager.pandafootball.system.dao.PersonDao;
import org.footballmanager.pandafootball.system.domain.Page;
import org.footballmanager.pandafootball.system.domain.Person;
import org.footballmanager.pandafootball.system.domain.PersonFromWeb;
import org.footballmanager.pandafootball.system.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class PersonServiceImpl extends ServiceImpl<Person> implements PersonService {
    @Autowired
    private PersonDao personDao;
    @Autowired
    private PageDao pageDao;

    /**
     * 根据状态和条目数获取数据
     *
     * @param status 状态
     * @param limit  条目数
     * @return 信息列表
     */
    @Override
    public List<Person> getStatusAndNumber(int status, int limit) {
        Example example = new Example(Person.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("process", false);
//        criteria.andEqualTo("status", status);
        criteria.andEqualTo("delFlag", 0);
        return personDao.selectByExampleAndRowBounds(example, new RowBounds(0, limit));
    }

    /**
     * 根据状态和条目数获取数据
     *
     * @param status 状态
     * @param limit  条目数
     * @return 信息列表
     */
    @Override
    public List<Page> getPageStatusAndNumber(int status, int limit) {
        Example example = new Example(Page.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("status", status);
        criteria.andEqualTo("delFlag", 0);
        return pageDao.selectByExampleAndRowBounds(example, new RowBounds(0, limit));
    }

    /**
     * 定时任务获取球员头像图片
     */
    //@Scheduled(cron = "0/5 * * * * ?")
    @Override
    public void getImage() {
        log.info("process qy img");
        List<Person> personList = this.getStatusAndNumber(0, 23);
        if (personList != null && !personList.isEmpty()) {
            for (Person person : personList) {
                boolean ok;
                try {
                    String url = SpiderUtil.processImageUrl("http://www.pesmaster.com/f-barrientos/pes-2018/player/", person.getName());
                    person.setImg(url);
                    ok = SpiderUtil.processImage(url, person.getName());
                } catch (Exception e) {
                    ok = false;
                }
                person.setProcess(ok);
                person.setStatus(1);
                this.updateNotNull(person, null);
            }
        }
    }

    /**
     * 定时任务获取球员信息
     */
//    @Scheduled(fixedRate = 999999999) //调试用触发方式
    //@Scheduled(cron = "0 0/1 * * * ?")
    @Override
    public void getPerson() {
        log.info("process qy");
        List<Person> personList = this.getStatusAndNumber(0, 10);
        if (personList != null && !personList.isEmpty()) {
            List<PersonFromWeb> list = new ArrayList<>();
            for (Person person : personList) {
                PersonFromWeb personFromWeb = SpiderUtil.processPerson(person.getUrl(), person.getName(), false);
                if (personFromWeb != null) {
                    log.info(personFromWeb.toString());
                    list.add(personFromWeb);
                    person.setProcess(false);
                } else {
                    person.setProcess(true);
                }
                person.setStatus(0);
                this.updateNotNull(person, null);
            }
            SpiderUtil.exportToExcel(list);
        }
    }

    /**
     * 定时任务处理页码并获取球员url
     */
    //@Scheduled(cron = "0 0/2 * * * ?")
    @Override
    public void processPage() {
        log.info("process page");
        List<Page> pageList = this.getPageStatusAndNumber(0, 20);
        if (pageList != null && !pageList.isEmpty()) {
            for (Page page : pageList) {
                Map<String, String> map = SpiderUtil.processPage("http://pesdb.net/pes2018", page.getUrl());
                page.setProcess(true);
                for (Map.Entry<String, String> entry : map.entrySet()) {
                    log.info("name=" + entry.getKey() + "url=" + entry.getValue());
                    newPerson(entry.getKey(), entry.getValue());
                }
                page.setStatus(1);
                pageDao.updateByPrimaryKeySelective(page);
            }
        }
    }

    /**
     * 一次性写入表格需要爬取数据的页码
     *
     * @param basePage 基页
     * @param start    开始页码
     * @param end      结束页码
     */
    @Override
    public void getPage(String basePage, Integer start, Integer end) {
        log.info("process page num");
        newPage(1, basePage);
        for (int i = start; i <= end; i++) {
            newPage(i, basePage + "?page=" + i);
        }
    }

    private void newPage(Integer num, String url) {
        Page page = new Page();
        page.setPageNum(num);
        page.setUrl(url);
        page.setProcess(false);
        page.setStatus(0);
        pageDao.insert(page);
    }

    private void newPerson(String name, String url) {
        Example example = new Example(Person.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("name", name);
        List<Person> list = personDao.selectByExample(example);
        if (list == null || list.isEmpty()) {
            Person p = new Person();
            p.setName(name);
            p.setUrl(url);
            p.setProcess(false);
            p.setStatus(0);
            personDao.insert(p);
        }
    }

    /**
     * 读取某个文件夹下的所有文件
     */
    @Override
    public boolean readTotalfile(String filename) throws IOException {
        try {
            File file = new File(filename);
            if (file.isFile()) {
                processTotalExcel(file);
            }
        } catch (FileNotFoundException e) {
            log.info("readfile()   Exception:" + e.getMessage());
        }
        return true;
    }

    private void processTotalExcel(File readfile) throws IOException {
        HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(readfile));
        HSSFSheet sheet = workbook.getSheetAt(0);
        for (int j = 1; j < sheet.getLastRowNum() + 1; j++) {// getLastRowNum，获取最后一行的行标
            HSSFRow row = sheet.getRow(j);
            if (row != null) {
                Cell cell = row.getCell(0);
                String id = cell.getStringCellValue();
                Example example = new Example(Person.class);
                Example.Criteria criteria = example.createCriteria();
                criteria.andEqualTo("name", Long.parseLong(id));
                List<Person> list = personDao.selectByExample(example);
                if (list != null && !list.isEmpty()) {
                    Person p = list.get(0);
                    if (p.getProcess() || p.getStatus().equals(1)) {
                        p.setProcess(false);
                        p.setStatus(0);
                        personDao.updateByPrimaryKeySelective(p);
                    }
                }
            }
        }
        log.info("读取sheet表：完成");
    }

    /**
     * 处理图像地址
     *
     * @param baseUrl 地址
     * @param suffix  后缀
     */
    @Override
    public void processImageUrl(String baseUrl, String suffix) {
        List<Person> list = this.getall();
        for (Person p : list) {
            p.setImg(baseUrl + p.getName() + suffix);
            p.setStatus(0);
            p.setProcess(false);
            this.updateNotNull(p, null);
        }
    }
}
